/**
 * 蓝图包装类
 */
import { generatorFunctionWithString,  execFunctionWithException } from "../utils";
const NODE = "node";
const TIMER = "timer";
const SERIAL = "serial";
const CONDITION = "condition";
export default class BlueprintFactory {
  private static instance: BlueprintFactory;
  public options: any;
  private compInstance = new Map();
  private timerId: Array<any> = [];
  private constructor(options: any) {
    this.options = options;
  }
  static getBlueprintInstance() {
    if (!this.instance) this.instance = new BlueprintFactory({});
    return this.instance;
  }
  /** 设置蓝图配置 */
  setOptions = (options: any) => {
    this.options = options;
  }
  /** 往蓝图中注册实际控件 */
  registerCompInstance = (id: string, instance: any) => {
    !this.compInstance.has(id) && this.compInstance.set(id, instance);
  }
  /** 递归链式调用核心: 实现图的深度优先遍历 */
  compose = (emitter: any) => {
    return (initParams: any) => {
      const dispatch = (next: Array<any> = [], params: any): any => {
        if (!next) return;
        next.forEach(config => {
          const targetType = this.options?.[config.id].type;
          let func;
          switch (targetType) {
            case NODE:
              func = this.__execCompInstanceAction;
              break;
            case SERIAL:
              func = this.__execSerialFunction;
              break;
            case TIMER:
              func = this.__execTimer;
              break;
            case CONDITION:
              func = this.__execCondition;
              break;
          }
          func && func(config, params, dispatch)
        })
      }
      return dispatch(emitter, initParams);
    }
  }
  /** 包装各个控件的事件方法 */
  wrapperEventFactory = (id: string, eventName: string) => {
    const config = this.options?.[id]?.[eventName];
    return config ? (ev: any) => {
      const composeFn = this.compose(config.next);
      composeFn(ev);
    } : undefined;
  }
  /** 执行控件中的动作 */
  __execCompInstanceAction = (config: any, params: any, next: any) => {
    const instance = this.compInstance.get(config.id);
    try {
      instance?.[config.actionName] ?  instance?.[config.actionName](params) : instance?.dispatchAction(config.actionName, params);
      const nextTarget = this.options?.[config.id];
      next(nextTarget);
    } catch {}
  }
  /** 执行串行处理函数 */
  __execSerialFunction = (config: any, params: any, next: any) => {
    const blueprintNode = this.options?.[config.id];
    const sreialFunc = generatorFunctionWithString(blueprintNode?.funcBody, "data");
    const result = execFunctionWithException(sreialFunc as Function, params, params);
    next(blueprintNode.next, result);
  }
  /** 创建定时器工作 */
  __execTimer = (config: any, params: any, next: any) => {
    const blueprintNode = this.options?.[config.id];
    const timer = setTimeout(() => {
      const nextTarget = this.options?.[config.id];
      next(nextTarget.next, params);
    }, blueprintNode.delay || 0);
    this.timerId.push(timer);
  }
  /** 执行多路选择 */
  __execCondition = (config: any, params: any, next: any) => {
    const nextTarget = this.options?.[config.id];
    params ? next(nextTarget?.trueNext, params) : next(nextTarget?.falseNext, params);
  }
  cleanUpBlueprint = () => {
    this.timerId.forEach(timer => clearInterval(timer));
  }
}